<?php
/**
 * 桌子管理
 */
namespace app\service;

use app\common\model\TableModel;
use think\facade\Cache;
use app\common\utils\RedisUtils;
use app\service\Chess;
use app\chess\Poker;
use app\handle\Table as hTable;
use app\common\model\RoomModel;

Class Table extends Union
{
    /**
     * 桌子数据表
     * @var [type]
     */
    public $t_model;

    /**
     * 返回结果
     * @var [type]
     */
    public $result;

    /**
     * 梭哈计数
     * @var [type]
     */
    public $allinCount;

    public function __construct()
    {
        parent::__construct();
        $this->t_model = new TableModel;
        $this->result = [
            'code' => 0,
            'msg'  => 'error'
        ];
        $this->allinCount = 0;
    }

    /**
     * 根据联盟id获取桌子信息
     *
     * @param  [type] $unionid [description]
     * @return [type]          [description]
     */
    public function getTableByUnionId($unionid)
    {
        $map = [
            'rid' => (int)$unionid
        ];
        $list = $this->t_model->where($map)
            ->all();

        $newList = [];
        foreach ($list as $k => &$v) {
            $htable = new hTable($v['id'], $v['uid']);
            $v['curInnings'] = $htable->getTableCurInnings();
            $v['curNumber'] = $htable->getTableNumber();
            $v['gameing'] = $htable->getGameStatus();
            if ((int)$v['curInnings'] < (int)$v['innings']) {
                array_push($newList, $v);
            }
        }

        return [
            'code' => 200,
            'rid'  => $unionid,
            'list' => json_encode($newList),
            'name' => (new RoomModel)->getFieldByRid($unionid, 'name')
        ];
    }

    /**
     * 创建牌桌
     *
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function createTable($data)
    {
        $data = $this->t_model->typeDataFormat($data);
        $create_neet_amount = (int)$this->c_model->get_value(CREATE_TABLE_AMOUNT);
        $ubalance = $this->u_service->getBalance($data['uid']);

        if (empty($data['low_grade'])) {
            return [
                'code' => 0,
                'msg'  => '下注低砖输入错误'
            ];
        }

        if (empty($data['min_balance'])) {
            return [
                'code' => 0,
                'msg'  => '最低余额输入错误'
            ];
        }

        if ($ubalance < $create_neet_amount) {
            return [
                'code' => 0,
                'msg'  => "您的砖石不足无法创建，创建所需{$create_neet_amount}颗砖石"
            ];
        }

        $data['id'] = $this->u_service->buildSixId('tables');
        $add = $this->t_model->save($data);
        if ($add > 0) {
            // 扣除余额并给用户发送信息
            $this->u_service->updateBalance($data['uid'], -$create_neet_amount);
            $msg = "创建牌桌扣除{$create_neet_amount}颗砖石";
            $this->u_service->sendEmailToUid($data['uid'], $msg);

            return [
                'code' => 200,
                'msg'  => '创建牌桌成功',
                'tid'  => $data['id']
            ];
        } else {
            return [
                'code' => 0,
                'msg'  => '创建牌桌失败'
            ];
        }
    }

    /**
     * 根据牌桌id加入牌桌
     *
     * @param  [type] $uid 用户id
     * @param  [type] $tid 牌桌id
     * @return [type]      [description]
     */
    public function joinTableByTid($uid, $tid)
    {
        // 判断用户是否断线重连
        $userExistTablePos = $this->isUserExistTablePos($uid);
        if ($userExistTablePos) {
            return $userExistTablePos;
        }

        // 判断牌桌是否已经存在
        $tableInfo = $this->t_model->isExistTable($tid);
        if (empty($tableInfo)) {
            $this->result['msg'] = '牌桌不存在';
            return $this->result;
        }
        if (!$this->isInningsSuccess($tableInfo['innings'], $tid)) {
            $this->result['msg'] = '牌桌不存在';
            return $this->result;
        }

        // 判断您的余额是否满足牌桌要求
        if (!$this->isMeetTable($uid, $tableInfo['min_balance'])) {
            $this->result['msg'] = "该牌桌最低砖石要求为{$tableInfo['min_balance']}颗";
            return $this->result;
        }

        // 判断牌桌的状态: 游戏中，已满员，局数是否已经使用完
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);
        if (!empty($tableRedis)) {
            if ((int)$tableInfo['number'] <= (int)$tableRedis['number']) {
                $this->result['msg'] = '牌桌已满员不可加入';
                return $this->result;
            }

            if ($tableRedis['gameing']) {
                $this->result['msg'] = '游戏已开始不可加入';
                return $this->result;
            }

            $joinTableRedis['innings'] = $tableRedis['innings'];
            $joinTableRedis['number'] = empty($tableRedis['number'])
                ? 0 : (int)$tableRedis['number'];
        } else {
            $joinTableRedis = [
                'number'  => 0,
                'gameing' => false,
                'innings' => 0
            ];
            RedisUtils::set($key, $joinTableRedis);
        }
        $joinTableRedis['number']++;

        // 加入房间位置
        $pos = $this->joinTablePos($uid, $tid);
        if (!$pos) {
            $this->result['msg'] = '进入牌桌位置失败';
            return $this->result;
        }
        $joinTableRedis['pos'] = $pos;
        RedisUtils::set($key, $joinTableRedis);
        RedisUtils::set(REDIS_TABLE.$tid, $pos);

        $result = [
            'code' => 200,
            'msg'  => '正在为您连接房间服务器...',
            'datas' => $joinTableRedis,
            'tid'   => $tid
        ];
        RedisUtils::set(REDIS_USER_TABLE.$uid, $result);
        return $result;
    }

    /**
     * 用户存在于其它牌桌
     *
     * @param  [type]  $uid [description]
     * @return boolean      [description]
     */
    public function isUserExistTablePos($uid)
    {
        $userTableRedis = RedisUtils::get(REDIS_USER_TABLE.$uid);
        if (empty($userTableRedis)) {
            return false;
        }

        $userTableRedis['code'] = 201;
        $userTableRedis['msg'] = '您当前正在游戏，正在为您重新连接...';
        return $userTableRedis;
    }

    /**
     * 初始化牌桌
     *
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function initTable($tid)
    {
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);

        if (empty($tableRedis)) {
            return false;
        }

        // 获取房间配置
        $tconfig = $this->t_model->get($tid);
        $homeownesId = $tconfig['uid'];
        $userinfo = [];
        foreach ($tableRedis['pos'] as $k => $v) {
            if (!empty($k)) {
                $uid = is_array($v) ? $k : $v;

                $uinfo = $this->u_service->u_model
                    ->where(['uid' => $uid])
                    ->find();
                $redisInfo = !empty($tableRedis['user'][$k]) ? $tableRedis['user'][$k] : [];

                if ($homeownesId == $uid) {
                    $status = 2;
                } elseif (!empty($redisInfo['status'])) {
                    $status = $redisInfo['status'];
                } else {
                    $status = 0;
                }
                $userinfo[$k] = [
                    'status'  => $status, // 准备状态 0-未准备 1-已准备 2-房主
                    'balance' => !empty($redisInfo['balance']) ? $redisInfo['balance'] : $uinfo['balance'],
                    'headimg' => $uinfo['headimg'],
                    'bet_balance' => !empty($redisInfo['bet_balance']) ? $redisInfo['bet_balance'] : 0,
                    'uid' => (string)$uid,
                    'username' => $this->u_service->getUsername($uid)
                ];
            }
        }
        $tableRedis['user'] = $userinfo;
        $tableRedis['config'] = [
            'is_send_text' => $tconfig['is_send_text'],
            'is_send_voice' => $tconfig['is_send_voice'],
            'min_balance' => $tconfig['min_balance'],
            'number' => $tconfig['number'],
            'low_grade' => $tconfig['low_grade'],
            'innings' => $tconfig['innings']
        ];
        $tableRedis['gameing'] = empty($tableRedis['gameing'])
            ? false : $tableRedis['gameing'];
        RedisUtils::set($key, $tableRedis);
        return true;
    }

    /**
     * 加入牌桌位置
     *
     * @param  [type] $uid [description]
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function joinTablePos($uid, $tid)
    {
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);

        if (empty($tableRedis)) return false;
        if (empty($tableRedis['pos'])) {
            $tableRedis['pos'] = array();
        }
        if (count($tableRedis['pos']) >= 5) return false;
        if (array_key_exists($uid, $tableRedis['pos'])) {
            return false;
        }

        $tableRedis['pos'][$uid] = [];
        return $tableRedis['pos'];
    }

    /**
     * 离开牌桌位置
     *
     * @param  [type] $uid [description]
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function leaveTablePos($uid, $tid)
    {
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);

        $user = $tableRedis['user'];
        $pos = $tableRedis['pos'];

        foreach ($user as $k => $v) {
            if ($uid == $v['uid']) {
                unset($user[$k]);
            }
        }

        foreach ($pos as $k => $v) {
            if ($uid == $k) {
                unset($pos[$k]);
            }
        }

        $tableRedis['user'] = $user;
        $tableRedis['pos'] = $pos;
        $tableRedis['number'] = $tableRedis['number'] - 1;
        if ($tableRedis['number'] < 0) {
            $tableRedis['number'] = 0;
        }
        RedisUtils::set($key, $tableRedis);
        RedisUtils::rm(REDIS_USER_TABLE.$uid);
        return true;
    }

    /**
     * 如果满足牌桌的最低余额则返回true
     *
     * @param  [type]  $uid             [description]
     * @param  [type]  $tableNeedAmount [description]
     * @return boolean                  [description]
     */
    public function isMeetTable($uid, $tableNeedAmount)
    {
        if ((int)$this->u_service->getBalance($uid) < (int)$tableNeedAmount) {
            return false;
        }
        return true;
    }

    /**
     * 判断局数是否已经没了
     *
     * @param  [type]  $totalInnings 总局数
     * @param  [type]  $tid          牌桌id
     * @return boolean               [description]
     */
    public function isInningsSuccess($totalInnings, $tid)
    {
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);

        if ((int)$tableRedis['innings'] <= (int)$totalInnings) {
            return true;
        }

        return false;
    }

    /**
     * 游戏准备或者不准备
     *
     * @param  [type] $uid [description]
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function gameReadyOrNotReady($uid, $tid)
    {
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);

        if (empty($tableRedis)) {
            return false;
        }
        if (!empty($tableRedis['gameing']) && $tableRedis['gameing']) {
            return false;
        }

        foreach ($tableRedis['user'] as $k => &$v) {
            if ($uid == $v['uid']) {
                $v['status'] = $v['status'] == 1 ? 0 : 1;
            }
        }
        RedisUtils::set($key, $tableRedis);
        return true;
    }

    /**
     * 开始游戏
     *
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function gameStart($tid)
    {
        $key = REDIS_TABLE_JOIN.$tid;
        $tableRedis = RedisUtils::get($key);
        $callKey = REDIS_CALL_CARDS.$tid;
        $result = [ 'code' => 0 ];

        if (empty($tableRedis)) {
            $result['msg'] = '房间不存在';
            return $result;
        }

        // 判断所有玩家是否都已经准备
        foreach ($tableRedis['user'] as $k => $v) {
            if ($v['status'] === 0) {
                $result['msg'] = '所有玩家都准备才可开始游戏';
                return $result;
            }
        }

        // 人数不足无法开始
        if ($tableRedis['number'] < 2) {
            $result['msg'] = '人数不足无法开始游戏';
            return $result;
        }

        // 判断游戏是否已经开始
        if (!empty($tableRedis['gameing']) && $tableRedis['gameing']) {
            $result['msg'] = '游戏已经开始';
            return $result;
        }

        // 开始游戏
        $tableRedis['innings']++;
        $tableRedis['gameing'] = true;
        $result['msg'] = '开始游戏';
        $result['code'] = 200;
        RedisUtils::set($key, $tableRedis);
        RedisUtils::rm($callKey);
        return $result;
    }

    /**
     * 发手牌
     *
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function sendLicensingToHand($tid)
    {
        $chess = new Chess($tid);
        $ckey = REDIS_TABLE_JOIN.$tid;      // 牌桌配置
        $pkey = REDIS_TABLE.$tid;           // 位置配置
        $cRedis = RedisUtils::get($ckey);    // 获取数据

        // 判断游戏是否开始
        if (empty($cRedis['gameing']) && !$cRedis['gameing']) {
            return false;
        }

        // 洗牌
        $chess->doShuffle();
        RedisUtils::set($pkey, $cRedis['pos']);

        // 按低注扣除用户砖石
        $lowGrade = $cRedis['config']['low_grade']; // 牌桌低注
        foreach ($cRedis['user'] as $k => &$v) {
            $this->u_service->updateBalance($v['uid'], 0-$lowGrade);
            $v['balance'] = $v['balance'] - $lowGrade;
            $v['bet_balance'] = $v['bet_balance'] + $lowGrade;
        }

        // 发手牌
        $cRedis['pos'] = $chess->licensingToHand();
        RedisUtils::set($ckey, $cRedis);
        $this->setCallShowSize($tid);
        return true;
    }

    /**
     * 比较牌面大小
     *
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function compareShowSize($tid)
    {
        $tkey = REDIS_TABLE_JOIN.$tid;
        $tRedis = RedisUtils::get($tkey);

        // 判断游戏是否开始
        if (empty($tRedis['gameing']) && !$tRedis['gameing']) {
            return false; // 游戏未开始
        }

        // 判断pos是否为空
        if (empty($tRedis['pos'])) {
            return false; // 未存在手牌
        }

        foreach ($tRedis['pos'] as $key => $value) {
            if (empty($key)) {
                continue 1;
            } else {
                // 获取牌数据
                $setMatrixString = '';
                $count = 1;
                foreach ($value as $ck => $cv) {
                    // 获取牌状态
                    if ($count === count($value)) {
                        foreach ($cv as $sk => $sv) {
                            $setMatrixString = $sk;
                        }
                    }
                    $count++;
                }

                // 获取点数
                if (empty($key)) {
                    $number = 0;
                } else {
                    $number = (new Poker)->setCardShowNumber($setMatrixString);
                }

                foreach ($tRedis['user'] as $uk => &$uv) {
                    if ($key == $uv['uid']) {
                        $uv['card_count'] = (int)$number;
                        $setp = empty($tRedis['setp']) ? 1 : $tRedis['setp'];
                        if (count($value) > $setp) {
                            $uv['speak']   = false;
                            $tRedis['setp'] = count($value);
                        } else {
                            $uv['speak'] = empty($uv['speak']) ? false : $uv['speak'];
                        }
                    }
                }
            }
        }

        RedisUtils::set($tkey, $tRedis);
        return true;
    }

    /**
     * 开始叫牌
     *
     * @param  [type] $tid  [description]
     * @param  [type] $data arrayString
     * @return [type]       [description]
     */
    public function startCallCrads($tid, $data)
    {
        $ckey = REDIS_CALL_CARDS.$tid;
        $cRedis = RedisUtils::get($ckey);

        if (empty($cRedis)) {
            $cRedis['time'] = time();
        }

        $downTime = 15 - (time() - $cRedis['time']);
        $cRedis['down'] = $downTime;

        if (!empty($data)) {
            $cRedis['call'] = json_decode($data, true);
        }

        if ($downTime < 0) {
            // 超时自动出牌
        }
        RedisUtils::set($ckey, $cRedis);
        return $cRedis;
    }

    /**
     * 过牌
     *
     * @param  [type] $tid [description]
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function aCrads($tid, $uid)
    {
        $ckey = REDIS_CALL_CARDS.$tid;
        $cRedis = RedisUtils::get($ckey);

        $call = $cRedis['call'];
        foreach ($call as $k => $v) {
            if ($uid == $v['uid']) {
                $index = $k;
                break;
            }
        }

        if ($call[$index]['speak'] || !$call[$index]['maxCount']) {
            return 2;
        }

        // 判断上一家是否加注, 如果已经加注则只能跟注、加注、弃牌、梭哈
        if (!empty($call[$index]['need_amount']) &&
            $call[$index]['need_amount'] > 0) {
            return 3;
        }

        if ($this->nextPlayer($tid, $uid)) {
            return 200;
        }

        return 1;
    }

    /**
     * 跟牌
     *
     * @param  [type] $args 0=>tid 1=>uid
     * @return [type]       [description]
     */
    public function withNote($tid, $uid)
    {
        $ckey = REDIS_CALL_CARDS.$tid;
        $tkey = REDIS_TABLE_JOIN.$tid;
        $cRedis = RedisUtils::get($ckey);
        $tRedis = RedisUtils::get($tkey);

        $config = $tRedis['config'];
        $user = $tRedis['user'];
        $call = $cRedis['call'];

        // 当前低注
        if (empty($cRedis['cur_low_grade'])) {
            $cRedis['cur_low_grade'] = $config['low_grade'];
        }
        $curLowGrade = $cRedis['cur_low_grade'];

        // 获取自己需要跟注的金额
        foreach ($call as $k => $v) {
            if ($uid == $v['uid']) {
                if (!empty($v['need_amount'])) {
                    $curLowGrade = $v['need_amount'];
                    break;
                }
            }
        }

        // User实例
        $umodel = $this->u_service;

        // 获取自己的余额
        $myBalance = $umodel->getBalance($uid);
        if ($myBalance <= $curLowGrade) {
            // allIn
            $betAmout = $myBalance;
            $allIn = true;
        } else {
            // withNote
            $betAmout = $curLowGrade;
            $allIn = false;
        }
        // 更新余额
        $umodel->updateBalance($uid, -$betAmout);

        // 更新用户redis下注状态
        foreach ($call as $k => $v) {
            if ($v['uid'] == $uid) { // 设置自己的状态
                $call[$k]['allin'] = $allIn;
                $call[$k]['need_amount'] = 0;
                $call[$k]['cur_amount'] = empty($v['cur_amount'])
                    ? $betAmout : $v['cur_amount'] + $betAmout;
            } else { // 设置其它人的状态
                $call[$k]['allin'] = empty($v['allin']) ? false : $v['allin'];
                $call[$k]['cur_amount'] = empty($v['cur_amount'])
                    ? 0 : $v['cur_amount'];

                if (empty($v['allin'])) {
                    if (empty($v['need_amount'])) {
                        $call[$k]['need_amount'] = $betAmout;
                    } else {
                        $need = $betAmout - $v['cur_amount'];
                        if ($need <= 0) {
                            $need = 0;
                        } else { // 需要重新说话
                            $call[$k]['speak'] = false;
                        }
                        $call[$k]['need_amount'] = $need;
                    }
                } else {
                    $call[$k]['need_amount'] = 0;
                }
            }
        }

        // 更新用户余额和投注状态
        foreach ($user as $k => $v) {
            if ($v['uid'] == $uid) {
                $user[$k]['balance'] = $v['balance']-$betAmout;
                $user[$k]['bet_balance'] = $v['bet_balance']+$betAmout;
            }
        }

        $cRedis['call'] = $call;
        $tRedis['user'] = $user;
        RedisUtils::set($tkey, $tRedis);
        RedisUtils::set($ckey, $cRedis);
        if ($this->nextPlayer($tid, $uid)) {
            return true;
        }

        return false;
    }

    /**
     * 加注
     *
     * @param  [type] $args 0=>tid 1=>uid 2=>*?
     * @return [type]       [description]
     */
    public function filling($tid, $uid, $times)
    {
        $ckey = REDIS_CALL_CARDS.$tid;
        $tkey = REDIS_TABLE_JOIN.$tid;
        $cRedis = RedisUtils::get($ckey);
        $tRedis = RedisUtils::get($tkey);

        $call = $cRedis['call'];
        $user = $tRedis['user'];
        $config = $tRedis['config'];

        // 当前低注
        if (empty($cRedis['cur_low_grade'])) {
            $cRedis['cur_low_grade'] = $times*$config['low_grade'];
        } else {
            $cRedis['cur_low_grade'] = $times*$cRedis['cur_low_grade'];
        }
        $curLowGrade = $cRedis['cur_low_grade'];

        // User实例
        $umodel = $this->u_service;

        // 获取自己的余额
        $myBalance = $umodel->getBalance($uid);
        if ($myBalance < $curLowGrade) {
            return 1; // 余额不足
        }
        $umodel->updateBalance($uid, -$curLowGrade);

        // 更新用户redis下注状态
        foreach ($call as $k => $v) {
            if ($v['uid'] == $uid) { // 设置自己的状态
                $call[$k]['allin'] = false;
                $call[$k]['need_amount'] = 0;
                $call[$k]['cur_amount'] = empty($v['cur_amount'])
                    ? $curLowGrade : $v['cur_amount'] + $curLowGrade;;
            } else { // 设置其它人的状态
                $call[$k]['allin'] = empty($v['allin']) ? false : $v['allin'];
                $call[$k]['cur_amount'] = empty($v['cur_amount'])
                    ? 0 : $v['cur_amount'];

                if (empty($v['allin'])) {
                    if (empty($v['need_amount'])) {
                        $call[$k]['need_amount'] = $curLowGrade;
                    } else {
                        $need = $curLowGrade - $v['cur_amount'];
                        if ($need <= 0) {
                            $need = 0;
                        } else { // 需要重新说话
                            $call[$k]['speak'] = false;
                        }
                        $call[$k]['need_amount'] = $need;
                    }
                } else {
                    $call[$k]['need_amount'] = 0;
                }
            }
        }

        // 更新用户余额和投注状态
        foreach ($user as $k => $v) {
            if ($v['uid'] == $uid) {
                $user[$k]['balance'] = $v['balance']-$curLowGrade;
                $user[$k]['bet_balance'] = $v['bet_balance']+$curLowGrade;
            }
        }

        $cRedis['call'] = $call;
        $tRedis['user'] = $user;
        RedisUtils::set($tkey, $tRedis);
        RedisUtils::set($ckey, $cRedis);
        if ($this->nextPlayer($tid, $uid)) {
            return true;
        }

        return false;
    }

    /**
     * 弃牌
     *
     * @param  [type] $args 0=>tid 1=>uid
     * @return [type]       [description]
     */
    public function disCrads($tid, $uid)
    {
        $ckey = REDIS_CALL_CARDS.$tid;
        $tkey = REDIS_TABLE_JOIN.$tid;
        $cRedis = RedisUtils::get($ckey);
        $tRedis = RedisUtils::get($tkey);

        $call = $cRedis['call'];

        $chess = new Chess($tid);
        $pos = $chess->discard($uid);
        $tRedis['pos'] = $pos;

        foreach ($call as $k => $v) {
            if ($uid == $v['uid']) {
                $call[$k]['disCrad'] = true;
                break;
            }
        }

        $cRedis['call'] = $call;
        RedisUtils::set($tkey, $tRedis);
        RedisUtils::set($ckey, $cRedis);
        if ($this->nextPlayer($tid, $uid)) {
            return true;
        }
        return false;
    }

    /**
     * 梭哈
     *
     * @param  [type] $args 0=>tid 1=>uid
     * @return [type]       [description]
     */
    public function allIn($tid, $uid)
    {
        $ckey = REDIS_CALL_CARDS.$tid;
        $tkey = REDIS_TABLE_JOIN.$tid;
        $cRedis = RedisUtils::get($ckey);
        $tRedis = RedisUtils::get($tkey);

        $user = $tRedis['user'];
        $call = $cRedis['call'];

        // User实例
        $umodel = $this->u_service;

        // 获取自己的余额
        $myBalance = $umodel->getBalance($uid);
        $umodel->updateBalance($uid, -$myBalance);

        // 更新用户redis下注状态
        foreach ($call as $k => $v) {
            if ($v['uid'] == $uid) { // 设置自己的状态
                $call[$k]['allin'] = true;
                $call[$k]['need_amount'] = 0;
                $call[$k]['cur_amount'] = empty($v['cur_amount'])
                    ? $myBalance : $v['cur_amount'] + $myBalance;
            } else { // 设置其它人的状态
                $call[$k]['allin'] = empty($v['allin']) ? false : $v['allin'];
                $call[$k]['cur_amount'] = empty($v['cur_amount'])
                    ? 0 : $v['cur_amount'];

                if (empty($v['allin'])) {
                    if (empty($v['need_amount'])) {
                        $call[$k]['need_amount'] = $myBalance;
                    } else {
                        $need = $myBalance - $v['cur_amount'];
                        if ($need <= 0) {
                            $need = 0;
                            $call[$k]['speak'] = true;
                        } else { // 需要重新说话
                            $call[$k]['speak'] = false;
                        }
                        $call[$k]['need_amount'] = $need;
                    }
                } else {
                    $call[$k]['need_amount'] = 0;
                }
            }
        }

        // 更新用户余额和投注状态
        foreach ($user as $k => $v) {
            if ($v['uid'] == $uid) {
                $user[$k]['balance'] = 0;
                $user[$k]['bet_balance'] = $v['bet_balance']+$myBalance;
            }
        }

        $cRedis['call'] = $call;
        $tRedis['user'] = $user;
        RedisUtils::set($tkey, $tRedis);
        RedisUtils::set($ckey, $cRedis);
        if ($this->nextPlayer($tid, $uid)) {
            return true;
        }

        return false;
    }

    /**
     * 上个叫牌完成转到下一个玩家
     *
     * @param  [type] $tid [description]
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function nextPlayer($tid, $uid)
    {
        $tkey = REDIS_TABLE_JOIN.$tid;
        $ckey = REDIS_CALL_CARDS.$tid;
        $tRedis = RedisUtils::get($tkey);
        $cRedis = RedisUtils::get($ckey);

        $user = $tRedis['user'];
        $call = $cRedis['call'];
        $cRedis['time'] = time(); // 重置倒计时

        $beforeUid = $this->nextUid($user, $call, $uid);
        if ($beforeUid == 'disCardsSettement') {
            // 全部弃牌直接结算
            $this->settleCurMatch($tid);
            return true;
        }

        if ($beforeUid == 'allinSendCard') {
            // 全部梭哈直接发牌
            RedisUtils::rm($ckey);
            $sendStatus = $this->sendCard($tid);
            if ($sendStatus === 200) { // 结算啦
                $this->settleCurMatch($tid);
                return true;
            }
            return true;
        }

        // 判断下一个叫牌玩家是否已经叫过牌
        foreach ($call as $k => $v) {
            if ($v['uid'] == $uid) {
                $call[$k]['maxCount'] = false;
                $call[$k]['speak'] = true;
                continue;
            }

            if ($v['uid'] == $beforeUid && !$v['speak']) {
                $call[$k]['maxCount'] = true;
                continue;
            }
        }

        // 判断所有玩家是否都已经叫完牌
        $callFlag = true;
        foreach ($call as $k => $v) {
            if (!$v['speak']) {
                $callFlag = false;
            }
        }
        if ($callFlag) { // 发牌
            RedisUtils::rm($ckey);
            $sendStatus = $this->sendCard($tid);
            if ($sendStatus === 200) { // 结算啦
                $this->settleCurMatch($tid);
                return true;
            }
        } else {
            $cRedis['call'] = $call;
            RedisUtils::set($ckey, $cRedis);
        }
        return true;
    }

    /**
     * 发牌
     *
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function sendCard($tid)
    {
        $tkey = REDIS_TABLE_JOIN.$tid;
        $ckey = REDIS_CALL_CARDS.$tid;
        $tRedis = RedisUtils::get($tkey);
        $cRedis = RedisUtils::get($ckey);

        $step = empty($tRedis['setp']) ? 2 : $tRedis['setp'];
        if (empty($step)) return false;

        // 如果步骤为最后一步，不需要发牌，直接结算
        if ($step > 4) {
            return 200;
        }

        $chess = new Chess($tid);
        $newPos = $chess->licensing($step);
        $tRedis['setp']++;
        $tRedis['pos'] = $newPos;
        RedisUtils::set($tkey, $tRedis);

        $this->setCallShowSize($tid);   // 设置叫牌流程
        return true;
    }

    /**
     * 设置叫牌流程
     *
     * @param [type] $tid [description]
     */
    public function setCallShowSize($tid)
    {
        $this->compareShowSize($tid);   // 比较牌面大小
        $tkey = REDIS_TABLE_JOIN.$tid;
        $ckey = REDIS_CALL_CARDS.$tid;
        $tRedis = RedisUtils::get($tkey);
        $cRedis = RedisUtils::get($ckey);

        $user = $tRedis['user'];
        if (empty($cRedis) || empty($cRedis['call'])) {
            $count = 0;
            foreach ($user as $k => $v) {
                $call[$count++] = [
                    'uid' => $v['uid'],
                    'count' => $v['card_count'],
                    'speak' => false,
                    'maxCount' => false
                ];
            }
            $cRedis['time'] = time();
        } else {
            $call = $cRedis['call'];
        }

        $maxCount = 0;
        $maxUid = 0;
        foreach ($user as $uk => $uv) {
            if ($uv['card_count'] > $maxCount) {
                $maxCount = $uv['card_count'];
                $maxUid = $uv['uid'];
            }

            // 重新赋值
            foreach ($call as $ck => &$cv) {
                if ($cv['uid'] == $uv['uid']) {
                    $cv['count'] = $uv['card_count'];
                    $cv['speak'] = false;
                    $cv['maxCount'] = false;
                }
            }
        }

        // 判断最大的牌面
        foreach ($call as $k => &$v) {
            if ($v['uid'] == $maxUid) {
                $v['maxCount'] = true;
                break;
            }
        }

        $cRedis['call'] = $call;
        RedisUtils::set($ckey, $cRedis);
        return true;
    }

    /**
     * 结算当前牌局
     *
     * @param  [type] $tid [description]
     * @return [type]      [description]
     */
    public function settleCurMatch($tid)
    {
        $tkey = REDIS_TABLE_JOIN.$tid;
        $tRedis = RedisUtils::get($tkey);
        $poker = new Poker();

        $pos = $tRedis['pos'];
        $user = $tRedis['user'];

        // 牌面全部打开
        $pos = $poker->cardsOpen($pos);
        $tRedis['pos'] = $pos;

        // 获取牌型大小
        $size = Poker::getCardsTypeAndNumber($pos);
        $tRedis['size'] = $size;
        $maxUid = Poker::getMaxUidByCardsSize($size);

        // 操作数据库结算余额
        $user = $this->u_service->settleMatch($user, $maxUid, $tid, $tRedis['innings']);
        $tRedis['user'] = $user;
        $tRedis['settle'] = true;
        $tRedis['settle_time'] = time();

        RedisUtils::set($tkey, $tRedis);
        return true;
    }

    /**
     * 重新开始游戏
     *
     * @return [type] [description]
     */
    public function reStartGame($tid)
    {
        $tkey = REDIS_TABLE_JOIN.$tid;
        $tRedis = RedisUtils::get($tkey);
        $newTRedis = [];

        $pos = $tRedis['pos'];
        $user = $tRedis['user'];
        $config = $tRedis['config'];

        if (!empty($tRedis['settle']) && !empty($tRedis['settle_time'])) {
            if (time() - $tRedis['settle_time'] > 5) {
                // 重置
                foreach ($pos as $k => &$v) {
                    $v[$k] = [];
                }

                foreach ($user as $k => &$v) {
                    $v[$k] = [
                        'status' => $v['status'] == 2 ? 2 : 0,
                        'balance' => $this->u_service->getBalance($v['uid']),
                        'headimg' => $v['headimg'],
                        'bet_balance' => 0,
                        'username' => $v['username'],
                        'uid' => $k
                    ];
                }

                $newTRedis['pos'] = $pos;
                $newTRedis['user'] = $user;
                $newTRedis['config'] = $config;
                $newTRedis['innings'] = $tRedis['innings'];
                $newTRedis['number'] = $tRedis['number'];
                $newTRedis['gameing'] = false;
            }
        }
    }

    /**
     * 获取下一个UID
     *
     * @param  [type] $user [description]
     * @param  [type] $call [description]
     * @param  [type] $uid  [description]
     * @return [type]       [description]
     */
    private function nextUid($user, $call, $uid)
    {
        $nUid = '';
        $disCount = 0; // 弃牌计数
        foreach ($user as $k => $v) {
            if ($v['uid'] == $uid) {
                break;
            }
            $nUid = $k;
        }
        if (empty($nUid) || $nUid == '') {
            $nUid = end($user)['uid'];
        }

        // 判断弃牌
        foreach ($call as $k => $v) {
            if (!empty($v['disCard']) && $v['disCard']) {
                $disCount++;
            }
        }
        if (count($call)-1 <= $disCount) {
            return 'disCardsSettement';
        }

        if (count($call)-1 <= $this->allinCount) {
            return 'allinSendCard';
        }

        // 获取UID
        foreach ($call as $k => $v) {
            if ($v['uid'] == $nUid) {
                if (!empty($v['disCard']) && $v['disCard']) {
                    return $this->nextUid($user, $call, $nUid);
                }

                if (!empty($v['allin']) && $v['allin']) {
                    $this->allinCount++;
                    return $this->nextUid($user, $call, $nUid);
                }
            }
        }

        return $nUid;
    }
}
